#include "utils.h"
#include "stdio.h"
#include <iostream>

float calcAngle(cv::Point2f a, cv::Point2f b, cv::Point2f c)
{
	float angle = atan2(b.y - a.y, b.x - a.x) - atan2(b.y - c.y, b.x - c.x); 
	angle *= 180. / CV_PI;
	if (angle > 360) angle -= 360;
	if (angle < 0) angle += 360;

	return angle;
}

cv::Mat flipLine(const cv::Mat & img, cv::Point center, float angle)
{
	cv::Point2f srcTri[3];
	cv::Point2f dstTri[3];

	double rad_phi = angle / 180. * CV_PI;
	double len = 5;

	srcTri[0] = center;
	srcTri[1] = cv::Point2f(center.x - len * cos(rad_phi), center.y + len * sin(rad_phi));
	srcTri[2] = cv::Point2f(center.x + len * sin(rad_phi), center.y + len * cos(rad_phi));

	dstTri[0] = center;
	dstTri[1] = cv::Point2f(center.x - len * cos(rad_phi), center.y + len * sin(rad_phi));
	dstTri[2] = cv::Point2f(center.x - len * sin(rad_phi), center.y - len * cos(rad_phi));

	cv::Mat warp_mat = getAffineTransform( srcTri, dstTri );

	cv::Mat dst;
	warpAffine(img, dst, warp_mat, img.size());

	return dst;
}

void findMaxContour(const cv::Mat & img, std::vector<cv::Point> & cont)
{
	std::vector<std::vector<cv::Point> > contour;
	cv::findContours(img.clone(), contour, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);

	if (contour.empty())
		return;

	int maxInd = 0;
	for (int i = 1; i < contour.size(); i++)
		if (contour[i].size() > contour[maxInd].size())
			maxInd = i;

	cont = contour[maxInd];
}

float radInscribedCircle(const cv::Mat & img)
{
	std::vector<cv::Point> cont;
	findMaxContour(img, cont);

	double maxDist = 0;
	for (int y = 0; y < img.rows; y++)
	{
		const uchar * img_row = img.ptr(y);
		for(int x = 0; x < img.cols; x++)
			if(img_row[x])
			{
				double curDist = pointPolygonTest(cont, cv::Point(x, y), true);
				if(curDist > maxDist)
					maxDist = curDist;
			}
	}
	return maxDist;

}


bool crop(const cv::Mat & src, cv::Mat & dst)
{
	int xmin = std::numeric_limits<int>::max();
	int ymin = std::numeric_limits<int>::max();
	int xmax = std::numeric_limits<int>::min();
	int ymax = std::numeric_limits<int>::min();
	for (int y = 0; y < src.rows; ++y) {
		for (int x = 0; x < src.cols; ++x) {
			if (src.at<uchar>(y, x) != 0) {
				xmin = std::min(xmin, x);
				ymin = std::min(ymin, y);
				xmax = std::max(xmax, x);
				ymax = std::max(ymax, y);
			}
		}
	}
	if (xmin > xmax || ymin > ymax || ymax >= src.rows || xmax >= src.cols) return false;

	dst = src(cv::Rect(xmin, ymin, xmax - xmin + 1, ymax - ymin + 1)).clone();
	cv::copyMakeBorder(dst, dst, 10, 10, 10, 10, cv::BORDER_CONSTANT, 0);
	return true;
}
